package cqrtplm.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import cqrtplm.util.RequestParamHolder;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE) // 确保最先执行
public class CachingRequestBodyFilter extends OncePerRequestFilter {


    @Resource
    private ObjectMapper objectMapper;

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                    HttpServletResponse response, 
                                    FilterChain filterChain)
            throws ServletException, IOException {
        
        // 只处理JSON请求
        String contentType = request.getContentType();
        if (contentType != null && contentType.contains("application/json")) {
            // 包装原始请求
            CachedBodyHttpServletRequestWrapper wrappedRequest =
                new CachedBodyHttpServletRequestWrapper(request);
            
            // 在这里提前处理请求体
            processRequestBody(wrappedRequest);
            
            // 继续过滤器链
            filterChain.doFilter(wrappedRequest, response);
        } else {
            filterChain.doFilter(request, response);
        }
    }

    private void processRequestBody(CachedBodyHttpServletRequestWrapper request) {
        try {
            String requestBody = request.getCachedBodyAsString();

            Map<String, Object> jsonMap = objectMapper.readValue(requestBody, Map.class);
            
            // 在这里提取 classId 和 masteroid
            // 实际项目中可以使用JSON解析库
            if (requestBody.contains("classId")) {
                // 提取逻辑
                extractParam(jsonMap, "classId");
            }
            if (requestBody.contains("masteredoid")) {
                // 提取逻辑
                extractParam(jsonMap, "masteredoid");
            }

            // 将提取的值存储到请求属性中
            request.setAttribute("classId", RequestParamHolder.getString("classId"));
            request.setAttribute("masteredoid", RequestParamHolder.getString("masteredoid"));
        } catch (Exception e) {
            // 错误处理
            System.err.println("Error processing request body: " + e.getMessage());
        }
    }


    private void extractParam(Map<String, Object> jsonMap, String paramKey) {
        try {
            Object value = findValueDeep(jsonMap, paramKey);
            if (value != null) {
                RequestParamHolder.put(paramKey, value);
            }
        } catch (Exception e) {
            System.err.println("Error extracting param '" + paramKey + "': " + e.getMessage());
        }
    }

    private Object findValueDeep(Map<String, Object> jsonMap, String targetKey) {
        for (Map.Entry<String, Object> entry : jsonMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            // 1. 直接匹配
            if (targetKey.equals(key)) {
                return value;
            }

            // 2. 嵌套Map中查找
            if (value instanceof Map) {
                Object nestedValue = findValueDeep((Map<String, Object>) value, targetKey);
                if (nestedValue != null) {
                    return nestedValue;
                }
            }

            // 3. 嵌套List中查找
            if (value instanceof java.util.List) {
                for (Object item : (java.util.List<?>) value) {
                    if (item instanceof Map) {
                        Object nestedValue = findValueDeep((Map<String, Object>) item, targetKey);
                        if (nestedValue != null) {
                            return nestedValue;
                        }
                    }
                }
            }
        }
        return null;
    }
}
